package pl.kosmowska.ewelina.server.dao;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;

import com.allen_sauer.gwt.log.client.Log;

import pl.kosmowska.ewelina.server.jdo.OutcomeData;

public class OutcomeDataDAO extends JdoDAOImpl<OutcomeData> {

	private static final Logger log = Logger.getLogger(OutcomeDataDAO.class
			.getName());

	public  OutcomeData findOutcomeData(String id) {
		return (OutcomeData) findById(id);
	}

	public  List<OutcomeData> findOutcomeDataByUser() {
		Long uid = UserDataDAO.getLoggedInUserId();

		String qfilter = "userId==" + uid + "";

		PersistenceManager pm = getPersistenceManager();
		try {
			javax.jdo.Query query = pm.newQuery("select from "
					+ OutcomeData.class.getName());
			query.setFilter(qfilter);
			List<OutcomeData> list = (List<OutcomeData>) query.execute();
			List<OutcomeData> r = (List<OutcomeData>) pm.detachCopyAll(list);

			return r;
		} catch (Exception e) {
			log.log(Level.SEVERE, e.getMessage());
			//e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;
	}

	public  List<OutcomeData> findOutcomeDataByUser(Date date){
		Long uid = UserDataDAO.getLoggedInUserId();

		String qfilter = "userId==" + uid + "";
		
		Date queryStartDate = getFirstDayOfMonth(date);
		Date queryEndDate = getLastDayOfMonth(date);

		PersistenceManager pm = getPersistenceManager();
		try {
			javax.jdo.Query query = pm.newQuery("select from "
					+ OutcomeData.class.getName()
					+ " WHERE this.userId == queryUserId "
					+ " && this.date >= queryStartDate && this.date <= queryEndDate "
					+ " PARAMETERS String queryUserId, java.util.Date queryStartDate, java.util.Date queryEndDate  "
					+ " ORDER BY date ASC");
			List<OutcomeData> list = (List<OutcomeData>) query.execute(uid, queryStartDate,queryEndDate);
			List<OutcomeData> r = (List<OutcomeData>) pm.detachCopyAll(list);

			return r;
		} catch (Exception e) {
			log.log(Level.SEVERE, e.getMessage());
		//	e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;
	}

	private Date getLastDayOfMonth(Date date) {
		java.util.Calendar calendar = Calendar.getInstance();
		calendar.clear();
		int daysNumber = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
		calendar.set(date.getYear() + 1900, date.getMonth(),
				daysNumber-1);
		return calendar.getTime();
	}

	private Date getFirstDayOfMonth(Date date) {
		java.util.Calendar calendar = Calendar.getInstance();
		calendar.set(date.getYear() + 1900, date.getMonth(),
				0);
		return calendar.getTime();
	}

	public  List<OutcomeData> findOutcomeDataByUser(boolean isOutcome,Date date) {
		Long uid = UserDataDAO.getLoggedInUserId();

		Date queryStartDate = getFirstDayOfMonth(date);
		Date queryEndDate = getLastDayOfMonth(date);

		PersistenceManager pm = getPersistenceManager();
		try {
			javax.jdo.Query query = query = pm.newQuery("SELECT FROM "
					+ OutcomeData.class.getName()
					+ " WHERE this.userId == queryUserId "
					+ " && this.date >= queryStartDate && this.date <= queryEndDate "
					+ " PARAMETERS String queryUserId, java.util.Date queryStartDate, java.util.Date queryEndDate ");

			List<OutcomeData> list = (List<OutcomeData>) query.execute(	uid,queryStartDate,queryEndDate);
			List<OutcomeData> detachedList = (List<OutcomeData>) pm.detachCopyAll(list);
			//Only one inequality sign for query possible
			return getOutcomeList(isOutcome, detachedList);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;
	}

	private List<OutcomeData> getOutcomeList(boolean isOutcome,
			List<OutcomeData> detachedList) {
		List<OutcomeData> returnedList = new ArrayList<OutcomeData>();

		if(isOutcome){
			for(OutcomeData data: detachedList){
				if (data.getValue()<0){
					returnedList.add(data);
				}
			}
		}else{
			for(OutcomeData data: detachedList){
				if (data.getValue()>0){
					returnedList.add(data);
				}
			}
		}


		return returnedList;
	}


	public  List<OutcomeData> findOutcomeDataByUserBetweenDates(boolean isOutcome,java.util.Date startDate, java.util.Date endDate) {
		Long uid = UserDataDAO.getLoggedInUserId();

		Date queryStartDate = initDate(startDate);
		Date queryEndDate = initDate(endDate);
		
		PersistenceManager pm = getPersistenceManager();
		try {

			final javax.jdo.Query query = pm
					.newQuery("SELECT FROM "
							+ OutcomeData.class.getName()
							+ " WHERE this.userId == queryUserId "
							+ " && this.date >= queryStartDate && this.date <= queryEndDate "
							+ " PARAMETERS String queryUserId, java.util.Date queryStartDate, java.util.Date queryEndDate");

			List<OutcomeData> list = (List<OutcomeData>) query.execute(uid,	queryStartDate, queryEndDate);
			List<OutcomeData> detachedList = (List<OutcomeData>) pm.detachCopyAll(list);

			return getOutcomeList(isOutcome, detachedList);
		} catch (Exception e) {;
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;
	}
	
	public  List<OutcomeData> findOutcomeDataByUserBetweenDates(java.util.Date startDate, java.util.Date endDate) {
		Long uid = UserDataDAO.getLoggedInUserId();

		Date queryStartDate = initDate(startDate);
		Date queryEndDate = initDate(endDate);
		

		PersistenceManager pm = getPersistenceManager();
		try {

			final javax.jdo.Query query = pm
					.newQuery("SELECT FROM "
							+ OutcomeData.class.getName()
							+ " WHERE this.userId == queryUserId "
							+ " && this.date >= queryStartDate && this.date <= queryEndDate "
							+ " PARAMETERS String queryUserId, java.util.Date queryStartDate, java.util.Date queryEndDate");

			List<OutcomeData> list = (List<OutcomeData>) query.execute(uid,	queryStartDate, queryEndDate);
			List<OutcomeData> detachedList = (List<OutcomeData>) pm.detachCopyAll(list);

			return detachedList;
		} catch (Exception e) {;
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;
	}

	private Date initDate(Date startDate) {
		java.util.Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(startDate.getYear() + 1900, startDate.getMonth(),
				startDate.getDate());
		return calendar.getTime();
	}


	public OutcomeData persist(OutcomeData outcomeData) {
		Log.error("OutcomeDataId"+outcomeData.getId());
		return (OutcomeData) persistEntity(outcomeData);
	}


	public List<OutcomeData> persistAll(List<OutcomeData> outcomeDataList) {

		Long uid = UserDataDAO.getLoggedInUserId();
		Iterator<OutcomeData> newListItr = outcomeDataList.iterator();

		while (newListItr.hasNext()) {
			OutcomeData tmp = newListItr.next();
			tmp.setUserId(uid);
			tmp.setVersion(01L);
		}
		PersistenceManager pm = getPersistenceManager();

		Transaction tx = pm.currentTransaction();
		try {
			Collection<OutcomeData> savedOutcomeDataList = pm.makePersistentAll(outcomeDataList);
			return (List<OutcomeData>) savedOutcomeDataList;

		} catch (Exception e) {
			log.log(Level.SEVERE, "Error:", e);
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;
	}
	
	public List<OutcomeData> persistAllRepeatedOutcome(List<OutcomeData> outcomeDataList) {

		Long uid = UserDataDAO.getLoggedInUserId();
		Iterator<OutcomeData> newListItr = outcomeDataList.iterator();

		while (newListItr.hasNext()) {
			OutcomeData tmp = newListItr.next();
			tmp.setUserId(uid);
			tmp.setVersion(01L);
		}
		PersistenceManager pm = getPersistenceManager();

		Transaction tx = pm.currentTransaction();
		try {
			Collection<OutcomeData> savedOutcomeDataList = pm.makePersistentAll(outcomeDataList);
			if(!savedOutcomeDataList.isEmpty()){
				Iterator<OutcomeData> savedOutcomeDataListItr = savedOutcomeDataList.iterator();
				OutcomeData firstFromCollection = savedOutcomeDataListItr.next();
				String groupId =firstFromCollection.getId();
				firstFromCollection.setGroupKey(groupId);
				while(savedOutcomeDataListItr.hasNext()){
					savedOutcomeDataListItr.next().setGroupKey(groupId);
				}
			}
			return (List<OutcomeData>) savedOutcomeDataList;

		} catch (Exception e) {
			log.log(Level.SEVERE, "Error:", e);
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;
	}


	public  List<OutcomeData> editRepeatedOutcomeData(
			String groupId, List<OutcomeData> newList, Date date) {
		Long uid = UserDataDAO.getLoggedInUserId();
		Date queryStartDate = initDate(date);

		PersistenceManager pm = getPersistenceManager();
		try {
			final javax.jdo.Query query = pm
					.newQuery("SELECT FROM "
							+ OutcomeData.class.getName()
							+ " WHERE this.userId == queryUserId "
							+ " && this.groupKey == groupId && this.date >= queryStartDate "
							+ " PARAMETERS String queryUserId, String groupId, java.util.Date queryStartDate,");

			List<OutcomeData> list = (List<OutcomeData>) query.execute(uid,	groupId, queryStartDate);

			if ((list == null) || (list.isEmpty())) {
				log.severe("OutcomeData.editRepeatedOutcomeData() Error: Empty list to edit, wrong query?");
				return null;
			}

			return swapLists(list, newList, pm);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;
	}


	public List<OutcomeData> editRepeatedOutcomeData(
			String groupId, List<OutcomeData> newList) {
		Long uid = UserDataDAO.getLoggedInUserId();
		String qfilter = "userId==" + uid + "";
		List<OutcomeData> editedList = null;

		PersistenceManager pm = getPersistenceManager();
		try {
			final javax.jdo.Query query = pm
					.newQuery("SELECT FROM "
							+ OutcomeData.class.getName()
							+ " WHERE this.groupKey == groupId "
							+ " PARAMETERS String groupId ");

			List<OutcomeData> list = (List<OutcomeData>) query.execute(	groupId);

			if ((list == null) || (list.isEmpty())) {
				log.severe("OutcomeData.editRepeatedOutcomeData() Error: Empty list to edit, wrong query?");
				return null;
			}

			return swapLists(list, newList, pm);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;
	}

	public List<OutcomeData> swapLists(List<OutcomeData> oldList,
			List<OutcomeData> newList, PersistenceManager pm) {
		Long uid = UserDataDAO.getLoggedInUserId();
		Iterator<OutcomeData> newListItr = newList.iterator();
		while (newListItr.hasNext()) {
			OutcomeData tmp = newListItr.next();
			tmp.setUserId(uid);
			tmp.setVersion(01L);
		}
		try {
			pm.deletePersistentAll(oldList);

			Collection<OutcomeData> savedOutcomeDataList = pm.makePersistentAll(newList);
			if(!savedOutcomeDataList.isEmpty()){
				Iterator<OutcomeData> savedOutcomeDataListItr = savedOutcomeDataList.iterator();
				OutcomeData firstFromCollection = savedOutcomeDataListItr.next();
				String groupId =firstFromCollection.getId();
				firstFromCollection.setGroupKey(groupId);
				while(savedOutcomeDataListItr.hasNext()){
					savedOutcomeDataListItr.next().setGroupKey(groupId);
				}
			}
			return (List<OutcomeData>) savedOutcomeDataList;

		} catch (Exception e) {
			log.log(Level.SEVERE, "Error:", e);
			e.printStackTrace();
		} 
		return null;
	}

	public  List<OutcomeData> deleteRepeatedOutcomeData(String groupId, Date date) {
		if (groupId == null) {
			return null;
		}
		Long uid = UserDataDAO.getLoggedInUserId();
		PersistenceManager pm = getPersistenceManager();
		List<OutcomeData> deletedList = null;

		String qfilter = "userId==" + uid + "";

		try {
			javax.jdo.Query query;
			List<OutcomeData> list;
			if (date!=null){
				Date queryStartDate = initDate(date);
				query = pm
						.newQuery("SELECT FROM "
								+ OutcomeData.class.getName()
								+ " WHERE this.groupKey == queryGroupKey && this.date >= queryStartDate "
								+ " PARAMETERS String queryGroupKey, java.util.Date queryStartDate ");

				list = (List<OutcomeData>) query.execute(groupId,queryStartDate);
			}else{
				query = pm
						.newQuery("SELECT FROM "
								+ OutcomeData.class.getName()
								+ " WHERE this.groupKey == queryGroupKey "
								+ " PARAMETERS String queryGroupKey ");
				list = (List<OutcomeData>) query.execute(groupId);
			}

			if ((list == null) || (list.isEmpty())) {
				log.severe("OutcomeData.deleteRepeatedOutcomeData() Error: Empty list to edit, wrong query?");
				return null;
			}
			deletedList = (List<OutcomeData>) pm.detachCopyAll(list);
			pm.deletePersistentAll(list);

		} catch (Exception e) {
			//e.printStackTrace();
		} finally {
			pm.close();
		}
		return deletedList;
	}

	public Float getSum(Date date) {

		Long uid = UserDataDAO.getLoggedInUserId();
		PersistenceManager pm = getPersistenceManager();

		Date queryStartDate = getFirstDayOfMonth(date);
		Date queryEndDate = getLastDayOfMonth(date);

		try {
			final javax.jdo.Query query = pm
					.newQuery("SELECT FROM "
							+ OutcomeData.class.getName()
							+ " WHERE this.userId == queryUserId "
							+ " && this.date >= queryStartDate && this.date <= queryEndDate "
							+ " PARAMETERS  String queryUserId, java.util.Date queryStartDate, java.util.Date queryEndDate");

			List<OutcomeData> list = (List<OutcomeData>) query.execute(uid,	queryStartDate, queryEndDate);
			return sum(list);
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return 0f;
	}

	private  Float sum(List<OutcomeData> list) {
		Float sum=0f;
		for(OutcomeData outcomeData: list){
			sum+=outcomeData.getValue();
		}
		return sum;
	}



	public List<OutcomeData> persistAllSavings(List<OutcomeData> outcomeDataList) {

		Long uid = UserDataDAO.getLoggedInUserId();
		Iterator<OutcomeData> newListItr = outcomeDataList.iterator();

		while (newListItr.hasNext()) {
			OutcomeData tmp = newListItr.next();
			tmp.setUserId(uid);
			if (tmp.getVersion() == null) {
				tmp.setVersion(0l);
			}
			tmp.setVersion(tmp.getVersion()+1);
		}
		PersistenceManager pm = getPersistenceManager();

		Transaction tx = pm.currentTransaction();
		try {
			Collection<OutcomeData> savedOutcomeDataList = pm.makePersistentAll(outcomeDataList);
			return (List<OutcomeData>) savedOutcomeDataList;

		} catch (Exception e) {
			log.log(Level.SEVERE, "Error:", e);
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;
	}

	public  List <OutcomeData> getSavingsOutcomeList(String id) {
		PersistenceManager pm = getPersistenceManager();
		Long uid = UserDataDAO.getLoggedInUserId();
		String qfilter = "userId==" + uid + "";

		try {
			final javax.jdo.Query query = pm
					.newQuery("SELECT FROM "
							+ OutcomeData.class.getName()
							+ " WHERE this.groupKey == groupId "
							+ " PARAMETERS String groupId ");

			List<OutcomeData> list = (List<OutcomeData>) query.execute(	id );

			if ((list == null) || (list.isEmpty())) {
				//	log.severe("OutcomeData.getSavingsOutcomeList() Error: Empty list returned, wrong query?");
				return null;
			}

			return list;
		} catch (Exception e) {
			log.log(Level.SEVERE,
					"Error: LoanData.findOutcomeDataByUser(): qfilter="
							+ qfilter, e);
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;

	}

	
	public Boolean deleteSponsoredOutcome(String id) {
		Long uid = UserDataDAO.getLoggedInUserId();

		String qfilter = "userId==" + uid + "";

		PersistenceManager pm = getPersistenceManager();
		try {
			javax.jdo.Query query;
			query = pm.newQuery("SELECT FROM "
					+ OutcomeData.class.getName()
					+ " WHERE this.sponsorKey == queryUserId  "
					+ " PARAMETERS String queryUserId ");

			query.deletePersistentAll(id);

			query.deletePersistentAll(	uid);
			return true;

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return false;
	}
}